<script lang="ts">
import { useElementSize, useLocalStorage, useTimeoutFn } from '@peng_kai/kit/libs/vueuse';
import Currency from '~/assets/imgs/lottery/currency.png';
import Direction from '~/assets/imgs/lottery/direction.png';
import GoldBg from '~/assets/imgs/lottery/gold-bg.png';
import Subtract from '~/assets/imgs/lottery/subtract.png';
import Title from '~/assets/imgs/lottery/title.png';
import Youwin from '~/assets/imgs/lottery/youwin.png';
import MusicBg from '~/assets/mp3/lottery/bg.mp3';
import Ing from '~/assets/mp3/lottery/ing.mp3';
import StartMp3 from '~/assets/mp3/lottery/on-start.mp3';
import ResultMp3 from '~/assets/mp3/lottery/result.mp3';
import { useModalBindHash } from '~/composables/url';
import { useAutoPopupController } from '~/composables/usePeriodicPopup';

export const lottery = useAntdModal({
  // eslint-disable-next-line import/no-self-import
  is: defineAsyncComponent(() => import('./Lottery.vue')),
}, {
  width: 'fit-content',
  maskClosable: false,
  closable: false,
  wrapClassName: 'ant-cover__Modal-lottery',
  footer: null,
  opener() {
    useModalBindHash({
      modalName: 'lottery',
      isOpen: () => !!lottery.modalProps.open,
      requireAuth: false,
      close: lottery.close,
      open: () => lottery.open(),
    });
  },
});
</script>

<script setup lang="ts">
const props = defineProps<{
  callback?: () => void;
}>();

const emits = defineEmits<{
  close: [];
}>();

const appStore = useAppStore();
const target = ref(null);
const swiper = ref(null);
const { width } = useElementSize(target);
const { deletePopup } = useAutoPopupController();
const router = useRouter();
const authed = useAuthed();
const { bonusesQry } = queries.useBonusesQuery();
const currencyStore = useCurrencyStore();
const isSpinning = useBoolean(false); // 转盘是否可用
const lotteryResults = useBoolean(false); // 转盘是否已结束
const musicBgPlay = useBoolean(true); // 背景音乐是否要播放
const startMp3 = ref<HTMLAudioElement | null>(null); // 点开始音乐
const progressBg = ref<HTMLAudioElement | null>(null); // 转圈
const resultBg = ref<HTMLAudioElement | null>(null); // 结果
const musicBg = ref<HTMLAudioElement | null>(null); // 背景
const slowRotation = ref<number | null>(null); // 自转角度
const winResult = ref<Api.GetData<typeof apis.apiActivityLuckySpinStart>>(); // 中奖结果标
const radius = computed(() => (toValue(width) / 2));

const { list, history, refetch, newUserAward } = useList();
const { bonusesAvailableAt, bonuses } = queries.useBonusesQuery();
const currencyList = computed(() => currencyStore.balanceList ?? []);
const luckyspinStorage = useLocalStorage('firstGiveaway', {});
const currentRotation = ref(0); // 旋转角度
const rotationTime = ref(100); // 初始过渡时间
// eslint-disable-next-line no-prototype-builtins
const isFiat = computed(() => currencyStore.fiatMap?.hasOwnProperty(currencyStore.cryptoName));
// 更新转盘函数
async function spinWheel() {
  try {
    if (isSpinning.is || !bonuses.value?.luckyspin?.available)
      return;
    isSpinning.setTrue();
    swiper?.value?.swiper.autoplay.pause();
    rotationTime.value = 5000;
    stopSlowRotation();
    await startLottery();

    // 重新请求倍数接口
    refetch();
    startMp3?.value?.play();
    setTimeout(() => (progressBg?.value?.play()), 200);
    const targetDegree = (winResult?.value?.result ?? 0) * 30 + 15;
    const circle = 8;
    currentRotation.value = 360 * circle + targetDegree;
    useTimeoutFn(() => {
      bonusesQry.refetch();
      swiper?.value?.swiper.autoplay.resume();
      if (winResult?.value?.result === toValue(newUserAward)) {
        // 关闭当前弹窗弹出注册奖励15u
        globalPopups.newUserAward?.open();
        emits('close');
      }
      useTimeoutFn(() => {
        progressBg?.value?.pause();
        lotteryResults.setTrue();
        resultBg?.value?.play();
        currencyStore.refetch();
      }, 200);
      useTimeoutFn(() => {
        isSpinning.setFalse();
        rotationTime.value = 100;
      }, 1000);
    }, rotationTime.value);
  }
  catch (e) {
    startSlowRotation();
    isSpinning.setFalse();
    rotationTime.value = 100;
  }
}

async function medium15u() {
  isSpinning.setTrue();
  swiper?.value?.swiper.autoplay.pause();
  rotationTime.value = 5000;
  stopSlowRotation();

  startMp3?.value?.play();
  setTimeout(() => (progressBg?.value?.play()), 200);
  const targetDegree = (winResult?.value?.result ?? 0) * 30 + 15;
  const circle = 8;
  currentRotation.value = 360 * circle + targetDegree;
  useTimeoutFn(() => {
    swiper?.value?.swiper.autoplay.resume();
    useTimeoutFn(() => {
      progressBg?.value?.pause();
      lotteryResults.setTrue();
      resultBg?.value?.play();
    }, 200);
    useTimeoutFn(() => {
      isSpinning.setFalse();
      rotationTime.value = 100;
      luckyspinStorage.value.firstDraw = true;
    }, 1000);
  }, rotationTime.value);
}

function onClose() {
  if (isSpinning.is)
    return;
  emits('close');
  'callback' in props && props?.callback?.();
  deletePopup('luckySpin');
}

// 开始自转
function startSlowRotation() {
  const rotate = () => {
    currentRotation.value += 0.2;
    slowRotation.value = requestAnimationFrame(rotate);
  };
  slowRotation.value = requestAnimationFrame(rotate);
}

// 停止自转
function stopSlowRotation() {
  if (slowRotation.value !== null)
    cancelAnimationFrame(slowRotation.value);
}

// 请求概率数组
function useList() {
  const { data, isLoading, refetch } = useQuery({
    queryKey: [apis.apiActivityLuckySpinReady.id],
    queryFn: () => apis.apiActivityLuckySpinReady(undefined),
  });

  // 设置默认值，让canvas马上绘制
  const list = computed(() => data?.value?.circle ?? []);
  const history = ref<any>([]);

  watchEffect(async () => {
    if (!!data?.value?.history && isSpinning.is) {
      await sleep(5500);
      history.value = data?.value?.history;
      return;
    }
    history.value = data?.value?.history;
  });

  const Loading = computed(() => isLoading?.value || false);
  const LotteryStatus = computed(() => data?.value?.status ?? undefined);

  const newUserAward = computed(() => list.value?.findIndex(i => i.type === 1));

  return {
    list,
    history,
    Loading,
    LotteryStatus,
    refetch,
    newUserAward,
  };
}

function currencyLogo(currency: string) {
  const current = currencyList.value.find(i => currency === i.currency);
  return appStore.joinCdnPath(current?.logo) || Currency;
}

async function startLottery() {
  winResult.value = await apis.apiActivityLuckySpinStart(undefined);
}

function onPlay() {
  emits('close');
  router.push('/');
}

function onShare() {
  globalPopups.lotteryShare?.open({ orderNo: (winResult?.value?.order_no ?? '') });
}

function toTransactions() {
  emits('close');
  router.push({
    name: RN.USER_TRANSATIONS,
    query: {
      active: 5,
      type: 10,
    },
  });
}

function onCountDownFinish() {
  setTimeout(() => {
    refetch();
    bonusesQry.refetch();
  }, 1000);
}

onMounted(() => {
  startSlowRotation();
});

watchEffect(() => {
  if (musicBgPlay.is)
    musicBg.value?.play();
  else
    musicBg.value?.pause();
});
</script>

<!--
  watch弹出一次后记录24小时后时间戳，判断当前时间是否大于时间戳时间，大于再次弹出，小于不弹出。
-->
<template>
  <div ref="target" class="outer-container" :class="{ finish: lotteryResults.is }">
    <div class="icons">
      <div class="icon" @click="musicBgPlay.toggle()">
        <TransitionGroup name="slide" tag="i">
          <i v-if="musicBgPlay.is" class="i-material-symbols:volume-up-outline-rounded absolute left-1.5 top-2.5 text-4.5" />
          <i v-else class="i-material-symbols:volume-off-outline-rounded absolute left-1.5 top-2.5 text-4.5" />
        </TransitionGroup>
      </div>
      <div class="icon" @click="onClose()">
        <i class="i-mingcute:close-line absolute right-1.5 top-2.5 text-4.5" />
      </div>
    </div>
    <div>
      <div v-if="lotteryResults.is || (!authed && luckyspinStorage.firstDraw)" class="result">
        <img :src="GoldBg" class="goldbg">
        <div class="win mb-5 pt-46 lt-tabletl:pt-28" :class="{ finish: lotteryResults.is }">
          <img :src="Youwin" class="w-62">
        </div>

        <div class="money" :class="{ finish: lotteryResults.is }">
          <div class="absolute left-50% top-50% w-100% translate-x--50% translate-y--50% text-center text-4 lt-tabletl:translate-y--60%" :class="{ '!translate-y--60%': authed }">
            <div class="text-7.1 font-900 leading-normal lt-tabletl:text-6">
              <template v-if="authed">
                <img :src="currencyLogo(list[(winResult?.result ?? 0)]?.currency)" class="mb-1 mr-2 h-7 w-7 align-middle">
                {{ list[(winResult?.result ?? 0)]?.amount }}
              </template>

              <template v-else>
                <TAmount v-if="isFiat" :value="currencyStore.convert('USD', 15, currencyStore.cryptoName)" :decimals="2" :symbol="(currencyStore.cryptoName === 'DIAMOND' ? 'USDT' : currencyStore.cryptoName)" format="fixed-dec" colored="inherit" iconPos="left" />
                <TAmount v-else :value="15" :decimals="2" symbol="USD" format="fixed-dec" colored="inherit" iconPos="left" />
              </template>
            </div>
          </div>
        </div>
        <div class="encourage mb-22.5 whitespace-pre-line text-center text-4 leading-6 lt-tabletl:mb-7.5" :class="{ finish: lotteryResults.is }">
          <template v-if="authed">
            {{ $t('tLnDg4EpbpoWlVo95gSho', { platform: appStore.appName }) }}
          </template>
          <template v-else>
            {{ $t('wRohGzYsbNtOlie1xyAi') }}
          </template>
        </div>

        <AButton
          v-if="authed"
          class="ant-cover__Button-3d-green w-37.5"
          type="primary"
          @click="onPlay"
        >
          {{ $t('ntRyJm12sCh9JbpJrKac') }}
        </AButton>

        <AButton
          v-if="!authed"
          class="ant-cover__Button-3d-green w-37.5"
          type="primary"
          @click="[globalPopups.sign.open?.({ view: 'signUp' }), onClose()]"
        >
          {{ $t('sx5fQf4CaYkEuTPtBdzg') }}
        </AButton>

        <div class="share mb-20 mt-5 flex-center cursor-pointer lt-tabletl:mb-14" :class="{ finish: lotteryResults.is }" @click="onShare">
          <template v-if="authed">
            <i class="i-ion:md-share-alt mr-1" />
            {{ $t('krbR46OfzBZB3QeKobZl') }}
          </template>
        </div>
      </div>
      <div v-else class="disc" :class="{ finish: lotteryResults.is }">
        <div class="flex flex-col items-center p-7">
          <div class="mb-2 mt-5 text-center lt-mobile:mb-1">
            <img :src="Title" class="h-6.5 w-54">
            <br>
            <p class="text-7.5 text-#FACC15 font-black">
              2 ETH
            </p>
          </div>

          <div class="plate">
            <div class="center" :style="`transform:rotate(${-currentRotation}deg);transition: transform ${rotationTime}ms cubic-bezier(.25,.44,.25,1.06) 0s; width: ${radius * 1.7}px;height: ${radius * 1.7}px;`" />
            <!-- 圆心 -->
            <img v-if="authed" :src="Subtract" class="subtract" :style="`width: ${radius / 3.7}px;height: ${radius / 3.7}px;`" @click="spinWheel">
            <img v-else :src="Subtract" class="subtract" :style="`width: ${radius / 3.7}px;height: ${radius / 3.7}px;`" @click="medium15u">

            <!-- 箭头 -->
            <img :src="Direction" class="direction">
          </div>

          <template v-if="authed">
            <AButton
              v-if="bonuses?.luckyspin?.available"
              class="ant-cover__Button-3d-primary min-w-37.5"
              type="primary"
              @click="spinWheel"
            >
              {{ $t('30Yo5rgLmbfWl6ksStHp') }}
            </AButton>

            <AButton
              v-else
              class="ant-cover__Button-3d-gray w-37.5"
              type="primary"
              disabled
            >
              <AStatisticCountdown
                class="ant-cover__StatisticCountdown-inline-inherit"
                :value="bonusesAvailableAt?.luckyspin" @fnish="onCountDownFinish"
              />
            </AButton>
          </template>
          <template v-else>
            <AButton
              class="ant-cover__Button-3d-primary min-w-37.5"
              type="primary"
              @click="medium15u"
            >
              {{ $t('30Yo5rgLmbfWl6ksStHp') }}
            </AButton>
          </template>

          <div v-if="authed" class="history mt-2.5 w-full flex justify-between" :class="{ finish: lotteryResults.is }">
            <div class="w-92%">
              <swiper-container
                ref="swiper"
                slidesPerView="4"
                :autoplay="{ delay: 2000 }"
                :loop="true"
                :freeMode="true"
                :width="width - 50"
              >
                <swiper-slide v-for="(i, k) in history" :key="k" class="flex items-center justify-start text-3 text-sys-text-ter">
                  <img :src="currencyLogo(i.currency)" class="mr-1 h-4.5 w-4.5"> {{ i?.amount }}
                </swiper-slide>
              </swiper-container>
            </div>
            <div class="h-5 w-5 flex-center rounded-2 bg-[#7b1b0cb0]" @click="toTransactions">
              <i class="i-iconamoon:history-bold text-3 text-sys-text-ter" />
            </div>
          </div>
        </div>
      </div>
    </div>

    <audio ref="startMp3" :src="StartMp3" preload="metadata" />
    <audio ref="progressBg" :src="Ing" preload="metadata" />
    <audio ref="resultBg" :src="ResultMp3" preload="metadata" />
    <audio ref="musicBg" :src="MusicBg" preload="metadata" loop />
  </div>
</template>

<style scoped lang="scss">
.outer-container {
  --uno: 'relative min-w-full';
  width: clamp(320px, 5.5vw + 320px, 560px);
  &::before {
    content: '';
    --uno: 'w-100% h-100% top-0 absolute';
    background: url('~/assets/imgs/lottery/bg.png') 50% / cover no-repeat;
    animation: enlarge 2s ease-in-out infinite;
  }

  &.finish {
    &::before {
      background: url('~/assets/imgs/lottery/win-bg.png') 50% / cover no-repeat;
    }
  }

  .icons {
    --uno: 'relative flex-between mx-2';
    .icon {
      --uno: 'z-10';

      &::before {
        content: '';
        --uno: 'block w-10 h-10 absolute';
      }
    }
  }

  .disc {
    .plate {
      --uno: 'relative my-4 flex-center';
      .center {
        --uno: 'relative flex-center';
        background: url('~/assets/imgs/lottery/disc1.png') 50% / cover no-repeat;
      }
      .subtract {
        --uno: 'absolute cursor-pointer transition-all duration-500 ';
      }
      .direction {
        --uno: 'absolute right-4 top-50% h-8.5 translate-x-30% lt-tabletl:h-6 -translate-y-50%';
      }
    }
  }

  .result {
    --uno: 'relative min-h-130 flex flex-col items-center';

    .money {
      --uno: 'relative h-14 w-52.25 mb-7.5';
      background: url('~/assets/imgs/lottery/flag.png') 50% / cover no-repeat;
    }

    .goldbg {
      --uno: 'absolute h-100% w-100% object-cover';
      animation: launch 0.6s ease-in-out forwards;
    }

    .win,
    .money {
      &.finish {
        animation: downshow 0.4s ease-in-out forwards;
      }
    }

    .encourage,
    .bit,
    .share {
      &.finish {
        animation: upshow 0.5s ease-in-out forwards;
      }
    }
  }

  .history {
    &.finish {
      animation: downhide 1s ease-in-out infinite;
    }
  }
}

.slide-enter-active,
.slide-leave-active {
  transition: all 0.3s ease;
}

.slide-enter-from,
.slide-leave-to {
  opacity: 0;
  transform: translateX(100%);
}

.slide-enter-to,
.slide-leave-from {
  opacity: 1;
  transform: translateX(0);
}
</style>

<style lang="scss">
.ant-modal-wrap.ant-cover__Modal-lottery {
  .ant-modal {
    .ant-modal-content {
      max-width: 560px;
      min-width: 320px;
      background: linear-gradient(0deg, #3b0401, #b81b1b) !important;
      border-radius: 16px;
      padding: 0px;
      overflow: hidden;
      position: relative;
    }
  }
}
</style>

<style>
@keyframes launch {
  0% {
    opacity: 0;
    transform: scale(0);
  }

  100% {
    opacity: 1;
    transform: scale(1);
  }
}

@keyframes downhide {
  0% {
    opacity: 1;
    transform: translateY(0);
  }

  100% {
    opacity: 0;
    transform: translateY(20px);
  }
}

@keyframes enlarge {
  0%,
  100% {
    transform: scale(1);
  }

  50% {
    transform: scale(1.02);
  }
}

@keyframes downshow {
  0% {
    opacity: 0;
    transform: translateY(30px);
  }

  100% {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes upshow {
  0% {
    opacity: 0;
    transform: translateY(-30px);
  }

  100% {
    opacity: 1;
    transform: translateY(0);
  }
}
</style>
